package cn.xu.framework.concurrent.queue;

import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import redis.clients.jedis.JedisCluster;

import javax.annotation.Resource;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.util.HashMap;
import java.util.Map;
import java.util.Random;
import java.util.Set;

/**
 * @author Clark Xu<clark2021@qq.com>
 * @date 2024/9/24
 */
public class DRQMonitorServlet extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.setContentType("text/html; charset=UTF-8");
        resp.setCharacterEncoding("UTF-8");
        String queuePipelineCluster = req.getParameter("jedisCluster");
        if(StringUtils.isBlank(queuePipelineCluster)){
            queuePipelineCluster = "queuePipelineCluster";
        }
        PrintWriter out = resp.getWriter();
        try {
            out.println("<!DOCTYPE html>");
            out.println("<html>");
            out.println("<head>");
            out.println("<meta charset=\"UTF-8\">");
            out.println("<title>Redis Queue Length Monitor</title>");
            out.println("<style>");
            out.println("table { width: 100%; border-collapse: collapse; }");
            out.println("th, td { border: 1px solid #ddd; padding: 8px; }");
            out.println("th { background-color: #f2f2f2; }");
            out.println("</style>");
            out.println("<script>");
            out.println(this.getChartJS());
            out.println("</script>");
            out.println("</head>");
            out.println("<body>");
            out.println("<h1>Redis Queue Length Monitor</h1>");
            out.println("<h3><span style=\"color:red;\">队列长度柱高上限100<span></h3>");
            JedisCluster jedisCluster = null;
            try {
                jedisCluster = (JedisCluster) ApplicationContextProvider.getBean(queuePipelineCluster);
            } catch (NoSuchBeanDefinitionException e) {
            }
            if(jedisCluster!=null){
                out.println("<canvas id=\"queueChart\" width=\"400\" height=\"200\"></canvas>");
                out.println("<table>");
                out.println("<thead>");
                out.println("<tr><th>Queue Name</th><th>Length</th></tr>");
                out.println("</thead>");
                out.println("<tbody>");
                Map<String, Integer> queueLengths = new HashMap<>();
                Map<String, Integer> queueChartLengths = new HashMap<>();
                DistributeRouteRedisLuaQueue distributeRouteRedisLuaQueue = ApplicationContextProvider.getBean(DistributeRouteRedisLuaQueue.class);
                Set<String> queueNames = distributeRouteRedisLuaQueue.getAllQueueNames();
                for (String queueName : queueNames) {
                    long length = jedisCluster.llen(queueName);
                    queueLengths.put(queueName, (int) length);
                    if(length > 99){
                        length = 100;
                    }
                    queueChartLengths.put(queueName, (int) length);
                }
                for (Map.Entry<String, Integer> entry : queueLengths.entrySet()) {
                    out.println("<tr>");
                    out.println("<td>" + entry.getKey() + "</td>");
                    out.println("<td>" + entry.getValue() + "</td>");
                    out.println("</tr>");
                }

                out.println("</tbody>");
                out.println("</table>");
                out.println("<script>");
                out.println("const ctx = document.getElementById('queueChart').getContext('2d');");
                out.println("const queueChartLengths = " + queueChartLengths.toString().replace("=", ":") + ";");
                out.println("const labels = Object.keys(queueChartLengths);");
                out.println("const data = Object.values(queueChartLengths);");

                out.println("const chart = new Chart(ctx, {");
                out.println("    type: 'bar',");
                out.println("    data: {");
                out.println("        labels: labels,");
                out.println("        datasets: [{");
                out.println("            label: 'Queue Length',");
                out.println("            data: data,");
                out.println("            backgroundColor: 'rgba(54, 162, 235, 0.2)',");
                out.println("            borderColor: 'rgba(54, 162, 235, 1)',");
                out.println("            borderWidth: 1");
                out.println("        }]");
                out.println("    },");
                out.println("    options: {");
                out.println("        scales: {");
                out.println("            y: {");
                out.println("                beginAtZero: true");
                out.println("            }");
                out.println("        }");
                out.println("    }");
                out.println("});");
                out.println("</script>");
            }else{
                out.println("jedisCluster not exists");
            }

            out.println("</body>");
            out.println("</html>");
        } catch (Exception e) {
            resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "Error retrieving queue lengths");
        }
    }

    private String getChartJS() throws IOException {
        // 获取当前类的类加载器
        ClassLoader classLoader = this.getClass().getClassLoader();
        // 获取指定文件的输入流
        InputStream inputStream = classLoader.getResourceAsStream("lua/ChartJs.v3.9.1.js");
        BufferedReader br = new BufferedReader(new InputStreamReader(inputStream));
        String str = null;
        StringBuffer sb = new StringBuffer();
        while((str = br.readLine()) != null) {
            sb.append(str).append("\n\t");
        }
        br.close();
        inputStream.close();
        return sb.toString();
    }
}
